﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using 粘贴板工具.Properties;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace 粘贴板工具
{
    public partial class Form1 : Form
    {
        #region Windows API函数
        [DllImport("user32.dll")]
        protected static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        protected static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        protected static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, Keys vk);

        [DllImport("user32.dll")]
        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        #endregion

        #region 全局变量
        private IntPtr nextClipboardViewer;
        private const int WM_DRAWCLIPBOARD = 0x0308;
        private const int WM_CHANGECBCHAIN = 0x030D;

        public const int WM_HOTKEY = 0x0312;
        private const int HOTKEY_ID = 22552; // 热键的唯一标识符
        private const uint MOD_ALT = 0x0001; // Alt 键

        List<ClipText> listClipText = new List<ClipText>();
        bool isShow = true;
        bool isClipClick = false;
        bool isExit = false;
        #endregion

        #region 构造函数
        public Form1()
        {
            InitializeComponent();
            nextClipboardViewer = SetClipboardViewer(this.Handle);
        }
        #endregion

        #region 初始化事件
        private void Form1_Load(object sender, EventArgs e)
        {
            RegisterHotKey(this.Handle, HOTKEY_ID, MOD_ALT, Keys.D1);
        }
        #endregion

        #region 消息处理回调事件
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_DRAWCLIPBOARD:
                    OnClipboardChanged();
                    if (nextClipboardViewer != IntPtr.Zero)
                    {
                        SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    }
                    break;
                case WM_CHANGECBCHAIN:
                    if (m.WParam == nextClipboardViewer)
                    {
                        nextClipboardViewer = m.LParam;
                    }
                    else if (nextClipboardViewer != IntPtr.Zero)
                    {
                        SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    }
                    break;
                case WM_HOTKEY:
                    if (m.WParam.ToInt32() == HOTKEY_ID)
                    {
                        if (this.isShow)
                        {
                            this.SetShowHide(false);
                        }
                        else
                        {
                            this.SetShowHide(true);
                        }
                    }
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        #endregion

        #region 第一次打开窗体事件
        private void Form1_Shown(object sender, EventArgs e)
        {
            this.SetShowHide(false);

            this.ClearClip();
        }
        #endregion

        #region 窗体关闭事件
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!this.isExit)
            {
                e.Cancel = true;
                this.SetShowHide(false);
            }
        }
        #endregion

        #region 系统菜单栏--图标点击事件
        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            this.SetShowHide(true);
        }
        #endregion

        #region 系统菜单栏-设置点击事件
        private void 设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
        #endregion

        #region 系统菜单栏-退出点击事件
        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UnregisterHotKey(this.Handle, HOTKEY_ID);
            this.isExit = true;
            Application.Exit();
        }
        #endregion

        #region 关闭按钮点击事件
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.SetShowHide(false);
        }
        #endregion

        #region 清空按钮点击事件
        private void btnClear_Click(object sender, EventArgs e)
        {
            this.ClearClip(true);
        }
        #endregion

        #region 设置显示隐藏
        /// <summary>
        /// 设置显示隐藏
        /// </summary>
        /// <param name="isShow">是否显示</param>
        private void SetShowHide(bool isShow)
        {
            if (isShow)
            {
                this.Show();
                this.isShow = true;
                //this.WindowState = FormWindowState.Normal;
            }
            else
            {
                this.Hide();
                this.isShow = false;
                //this.WindowState = FormWindowState.Minimized;
            }
        }
        #endregion

        #region 剪贴板变更
        private void OnClipboardChanged()
        {
            if (!this.isClipClick && Clipboard.ContainsText())
            {
                string clipboardText = Clipboard.GetText();

                //剪贴文本为空时，不记录
                if (string.IsNullOrWhiteSpace(clipboardText))
                {
                    return;
                }

                this.AddClip(clipboardText);
            }
        }
        #endregion

        #region 清空剪贴板
        public void ClearClip(bool nonTop = false)
        {
            if (!nonTop)
            {
                this.listClipText.Clear();
            }
            else
            {
                var delList =this.listClipText.Where(x => !x.isTop).ToList();

                if (delList.Any())
                {
                    foreach (var del in delList)
                    {
                        this.listClipText.Remove(del);
                    }
                }
            }
            this.RefreshText();
        }
        #endregion

        #region 新增剪贴板
        public void AddClip(string text)
        {
            //剪贴内容与上一次相同时，不重复记录
            string lastText = "";
            if (this.listClipText.Any())
            {
                lastText = this.listClipText.First().text;
            }
            if (lastText != text)
            {
                var temp = this.listClipText.OrderByDescending(x => x.index).FirstOrDefault();

                this.listClipText.Insert(0, new ClipText()
                {
                    index = temp == null ? 0 : temp.index + 1,
                    text = text
                });
                this.RefreshText();
            }
        }
        #endregion

        #region 刷新
        /// <summary>
        /// 刷新
        /// </summary>
        public void RefreshText()
        {
            this.panel1.Controls.Clear();

            if (this.listClipText.Any())
            {
                var index = 0;
                //添加置顶
                var tempList = this.listClipText.Where(x => x.isTop).OrderByDescending(x => x.index);
                if (tempList.Any())
                {
                    foreach (var item in tempList)
                    {
                        this.AddContorl(item, index);
                        index++;
                    }
                }

                tempList = this.listClipText.Where(x => !x.isTop).OrderByDescending(x => x.index);
                if (tempList.Any())
                {
                    foreach (var item in tempList)
                    {
                        this.AddContorl(item, index);
                        index++;
                    }
                }
            }
        }
        #endregion

        #region 新增剪贴内容控件
        private void AddContorl(ClipText clipText, int index)
        {
            //新增内容按钮
            var btnClipText = new System.Windows.Forms.Button();
            btnClipText.Location = new Point(17, 3 + (index * 76));
            btnClipText.Name = $"btnClipText{clipText.index}";
            btnClipText.Size = new Size(348, 70);
            btnClipText.TabStop = false;
            btnClipText.TextAlign = ContentAlignment.TopLeft;
            btnClipText.UseVisualStyleBackColor = true;
            btnClipText.Click += new EventHandler(this.btnClipText_Click);
            btnClipText.Text = clipText.text;
            this.panel1.Controls.Add(btnClipText);

            //新增置顶按钮
            var btnTop = new System.Windows.Forms.Button();

            if (clipText.isTop)
            {
                btnTop.Image = Resources.置顶;
            }
            else
            {
                btnTop.Image = Resources.取消置顶;
            }

            btnTop.Location = new Point(338, 46 + (index * 76));
            btnTop.Name = $"btnTop{clipText.index}";
            btnTop.Size = new Size(24, 24);
            btnTop.TabStop = false;
            btnTop.UseVisualStyleBackColor = true;
            btnTop.Click += new EventHandler(this.btnTop_Click);
            this.panel1.Controls.Add(btnTop);
            btnTop.BringToFront();

            var toolTip = new System.Windows.Forms.ToolTip();
            toolTip.SetToolTip(btnClipText, clipText.text);
        }
        #endregion

        #region 剪贴内容点击事件
        private void btnClipText_Click(object sender, EventArgs e)
        {
            try
            {
                var btnClipText = (System.Windows.Forms.Button)sender;
                int index = int.Parse(btnClipText.Name.Substring(11));
                var clipText = this.listClipText.Where(x => x.index == index).FirstOrDefault();

                if (clipText != null)
                {
                    isClipClick = true;
                    Clipboard.SetText(clipText.text);
                    isClipClick = false;
                }
            }
            catch (Exception)
            {
            }
        }
        #endregion

        #region 置顶按钮点击事件
        private void btnTop_Click(object sender, EventArgs e)
        {
            var btnTop = (System.Windows.Forms.Button)sender;
            int index = int.Parse(btnTop.Name.Substring(6));

            var clipText = this.listClipText.Where(x => x.index == index).FirstOrDefault();

            if (clipText.isTop)
            {
                btnTop.Image = Resources.取消置顶;
                clipText.isTop = false;
            }
            else
            {
                btnTop.Image = Resources.置顶;
                clipText.isTop = true;
            }
            this.RefreshText();
        }
        #endregion
    }
}
